package com.lanyan.web.controller.courier;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import com.lanyan.common.core.controller.BaseController;
import com.lanyan.common.core.domain.AjaxResult;
import com.lanyan.common.core.domain.PageR;
import com.lanyan.common.core.domain.R;
import com.lanyan.common.utils.SecurityUtils;
import com.lanyan.common.utils.StringUtils;
import com.lanyan.framework.web.service.SysLoginService;
import com.lanyan.system.domain.*;
import com.lanyan.system.domain.vo.BuildingVo;
import com.lanyan.system.domain.vo.OrdersItemVo;
import com.lanyan.system.domain.vo.OrdersVo;
import com.lanyan.system.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Year;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoField;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 配送员Controller
 *
 * @author lanyan
 * @date 2024-11-26
 */
@RestController
@Api(tags = {"配送员-订单"})
@RequestMapping("/courier/orders")
public class CourierOrdersController extends BaseController {
    @Autowired
    private IOrdersService ordersService;
    @Autowired
    private IOrdersItemService ordersItemService;
    @Autowired
    private IProductService productService;
    @Autowired
    private ISkuService skuService;
    @Autowired
    private IBuildingService buildingService;
    @Autowired
    private IEstateService estateService;
    @Autowired
    private IInformService informService;

    /**
     * 查询订单列表
     */
    @GetMapping("/page")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "订单类型（0商城订单 1取送订单）", dataType = "String", dataTypeClass = String.class),
            @ApiImplicitParam(name = "secondType", value = "取送类型（0帮取 1帮送）", dataType = "String", dataTypeClass = String.class),
            @ApiImplicitParam(name = "state", value = "订单状态（1待接单 2进行中 3已完成）", dataType = "String", dataTypeClass = String.class),
            @ApiImplicitParam(name = "timeType", value = "时间范围（0本日 1本周 2本月）", dataType = "String", dataTypeClass = String.class),
            @ApiImplicitParam(name = "isReceive", value = "是否接取（0未接取 1已接取）", dataType = "String", dataTypeClass = String.class),
            @ApiImplicitParam(name = "startTime", value = "开始时间", dataType = "String", dataTypeClass = String.class),
            @ApiImplicitParam(name = "endTime", value = "结束时间", dataType = "String", dataTypeClass = String.class),
            @ApiImplicitParam(name = "pageNum", value = "第几页", dataType = "int", dataTypeClass = int.class),
            @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", dataTypeClass = int.class),
    })
    @ApiOperation("查询订单列表")
    public PageR<OrdersVo<OrdersItemVo>> list(@ApiIgnore Orders<OrdersItemVo> orders) {
        Long courierId = SecurityUtils.getUserId();
        List<Building> buildingList = buildingService.lambdaQuery()
                .eq(BuildingVo::getDelFlag, "0")
                .eq(BuildingVo::getCourierId, courierId)
                .list();
        List<Long> collect = buildingList.stream().map(BuildingVo::getBuildingId).collect(Collectors.toList());
        if (collect.size() == 0){
            collect.add(0L);
        }

        // 根据订单类型和其他条件构建查询
        LambdaQueryChainWrapper<Orders> wrapper = ordersService.lambdaQuery();
        wrapper.eq(Orders::getDelFlag, "0");
        if (StringUtils.isNotEmpty(orders.getType())) {
            wrapper.eq(Orders::getType, orders.getType());
            if (StringUtils.equals(orders.getType(), "0")) {
                if (StringUtils.equals(orders.getIsReceive(), "0")) {
                    wrapper.isNull(Orders::getCourierId);
                    if (collect.size() != 0){
                        wrapper.in(Orders::getSendBuilding,collect);
                    }else {
                        wrapper.isNull(Orders::getSendBuilding);
                    }
                } else {
                    wrapper.eq(Orders::getCourierId, courierId);
                }
            } else {
                if (StringUtils.equals(orders.getIsReceive(), "0")) {
                    wrapper.isNull(Orders::getCourierId)
                            .and(x -> x.and(y -> y.eq(Orders::getSecondType, "0").in(Orders::getFetchBuilding, collect))
                                    .or(y -> y.eq(Orders::getSecondType, "1").in(Orders::getFetchBuilding, collect)));
//                            .and(x -> x.and(y -> y.eq(Orders::getSecondType, "0").in(Orders::getFetchBuilding, collect))
//                                    .or(y -> y.eq(Orders::getSecondType, "1").in(Orders::getSecondType, collect)));
                } else {
                    wrapper.eq(Orders::getCourierId, courierId);
                }
            }
        } else {
            wrapper.eq(OrdersVo::getCourierId, courierId);
        }

        // 添加其他条件
        if (StringUtils.isNotEmpty(orders.getSecondType())) {
            wrapper.eq(Orders::getSecondType, orders.getSecondType());
        }
        if (StringUtils.isNotEmpty(orders.getState())) {
            wrapper.eq(Orders::getState, orders.getState());
        }
        if (StringUtils.isNotEmpty(orders.getStartTime())) {
            orders.setStartTime(orders.getStartTime() + " 00:00:00");
            orders.setEndTime(orders.getEndTime() + " 23:59:59");
            wrapper.between(Orders::getCreateTime, orders.getStartTime(), orders.getEndTime());
        }
        addTimeTypeCondition(wrapper, orders); // 提取时间类型处理逻辑到单独方法

        startPage();

        List<Orders> ordersList = wrapper.list(); // 注意：这里可能需要根据实际API调整
        long total = new PageInfo<>(ordersList).getTotal();
        List<OrdersVo<OrdersItemVo>> list = new ArrayList<>();

        for (Orders item : ordersList) {
            OrdersVo<OrdersItemVo> ordersVo = convertToOrdersVo(item);

            ordersVo.setOrdersItemVoList(ordersItemService.lambdaQuery()
                    .eq(OrdersItem::getDelFlag, "0")
                    .eq(OrdersItem::getOrdersId, ordersVo.getOrdersId())
                    .list()
                    .stream()
                    .map(this::convertToOrdersItemVo) // 如果需要，也可以提取转换逻辑到单独方法
                    .collect(Collectors.toList()));

            if (StringUtils.isNotEmpty(item.getFetchBuilding())) {
                Building building = buildingService.getById(item.getFetchBuilding());
                Estate estate = estateService.getById(building.getEstateId());
                ordersVo.setFetchEstate(estate.getName() + building.getName());
            }
            if (StringUtils.isNotEmpty(item.getSendBuilding())) {
                Building building = buildingService.getById(item.getSendBuilding());
                Estate estate = estateService.getById(building.getEstateId());
                ordersVo.setSendEstate(estate.getName() + building.getName());
            }
            list.add(ordersVo);
        }
        PageR<OrdersVo<OrdersItemVo>> res = PageR.page(list);
//        res.setTotal(new PageInfo(ordersList).getTotal());
        res.setTotal(total);
        return res;
    }


    /**
     * 获取订单详细信息
     */
    @GetMapping(value = "/info")
    @ApiOperation("获取订单详细信息")
    public R<Orders<OrdersItem>> getInfo(Long ordersId) {
        Orders orders = ordersService.getById(ordersId);
        List<OrdersItem> ordersItemList = ordersItemService.lambdaQuery()
                .eq(OrdersItem::getDelFlag, "0")
                .eq(OrdersItem::getOrdersId, orders.getOrdersId())
                .list();
        orders.setOrdersItemVoList(ordersItemList);
        if (StringUtils.isNotEmpty(orders.getFetchBuilding())) {
            Building building = buildingService.getById(orders.getFetchBuilding());
            Estate estate = estateService.getById(building.getEstateId());
            orders.setFetchEstate(estate.getName() + building.getName());
        }
        if (StringUtils.isNotEmpty(orders.getSendBuilding())) {
            Building building = buildingService.getById(orders.getSendBuilding());
            Estate estate = estateService.getById(building.getEstateId());
            orders.setSendEstate(estate.getName() + building.getName());
        }
        return R.ok(orders);
    }

    /**
     * 接单
     */
    @GetMapping("/take")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "ordersIds", value = "订单id，多个用,拼接", dataType = "String", dataTypeClass = String.class),
    })
    @ApiOperation("接单")
    public R take(String ordersIds) {
        String[] split = ordersIds.split(",");
        ordersService.lambdaUpdate()
                .eq(Orders::getDelFlag, "0")
                .in(OrdersVo::getOrdersId, split)
                .set(Orders::getCourierId, SecurityUtils.getUserId())
                .set(OrdersVo::getState, "2")
                .update();
        for (String ordersId : split) {
            Orders orders = ordersService.getById(ordersId);
            Inform inform = new Inform();
            inform.setAccountId(orders.getAccountId());
            inform.setType("1");
            inform.setTitle("订单提醒");
            inform.setCreateTime(new Date());
            inform.setContent(StringUtils.format("您有一笔订单（订单号：{}）正在派送中，请及时查收~",orders.getOrdersNo()));
            informService.save(inform);
        }
        return R.ok();
    }

    /**
     * 结束订单
     */
    @GetMapping("/over")
    @ApiOperation("结束订单")
    public R over(String ordersId, String code) {
        Orders orders = ordersService.getById(ordersId);
        if (StringUtils.equals(orders.getType(),"1") && !StringUtils.equals(orders.getCode(), code.toUpperCase())) {
            return R.fail("取货码错误");
        }
        ordersService.lambdaUpdate()
                .eq(OrdersVo::getOrdersId, ordersId)
                .set(OrdersVo::getState, "3")
                .update();
        Inform inform = new Inform();
        inform.setAccountId(orders.getAccountId());
        inform.setType("1");
        inform.setTitle("订单提醒");
        inform.setCreateTime(new Date());
        inform.setContent(StringUtils.format("您有一笔订单（订单号：{}）已派送成功",orders.getOrdersNo()));
        informService.save(inform);
        return R.ok();
    }

    /**
     * 统计未接订单数
     */
    @GetMapping("/count")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "订单类型（0商城订单 1取送订单）", dataType = "String", dataTypeClass = String.class),
            @ApiImplicitParam(name = "secondType", value = "取送类型（0帮取 1帮送）", dataType = "String", dataTypeClass = String.class),
    })
    @ApiOperation("统计未接订单数")
    public R count(String type, String secondType) {
        LambdaQueryChainWrapper<Orders> wrapper = ordersService.lambdaQuery()
                .eq(Orders::getCourierId, SecurityUtils.getUserId());
        if (StringUtils.isNotEmpty(type)) {
            wrapper.eq(Orders::getType, type);
        }
        if (StringUtils.isNotEmpty(secondType)) {
            wrapper.eq(Orders::getSecondType, secondType);
        }
        Integer count = wrapper.count();
        return R.ok(count);
    }

    /**
     * 统计订单数
     */
    @GetMapping("/countAll")
    @ApiOperation("统计订单数")
    public R countAll() {
        Map<String, Integer> res = new HashMap<>();
        Integer all = ordersService.lambdaQuery()
                .eq(Orders::getDelFlag, "0")
                .eq(Orders::getCourierId, SecurityUtils.getUserId())
                .ne(OrdersVo::getState,"4")
                .count();
        LocalDate today = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd 00:00:00");
        Integer todayCount = ordersService.lambdaQuery()
                .eq(Orders::getDelFlag, "0")
                .eq(Orders::getCourierId, SecurityUtils.getUserId())
                .gt(OrdersVo::getReceivingTime, today.format(formatter))
                .count();

        // 获取本周的开始日期（假设周一为一周的开始）
        LocalDate startOfWeek = today.with(ChronoField.DAY_OF_WEEK, 1);
        Integer weekCount = ordersService.lambdaQuery()
                .eq(Orders::getDelFlag, "0")
                .eq(Orders::getCourierId, SecurityUtils.getUserId())
                .gt(OrdersVo::getReceivingTime, startOfWeek.format(formatter))
                .count();

        // 获取本月的开始日期
        LocalDate startOfMonth = today.withDayOfMonth(1);
        Integer monthCount = ordersService.lambdaQuery()
                .eq(Orders::getDelFlag, "0")
                .eq(Orders::getCourierId, SecurityUtils.getUserId())
                .gt(OrdersVo::getReceivingTime, startOfMonth.format(formatter))
                .count();
        res.put("all", all);
        res.put("todayCount", todayCount);
        res.put("weekCount", weekCount);
        res.put("monthCount", monthCount);
        return R.ok(res);
    }

    // 提取时间类型处理逻辑的方法
    private void addTimeTypeCondition(LambdaQueryChainWrapper<Orders> wrapper, Orders orders) {
        if (StringUtils.isNotEmpty(orders.getTimeType())) {
            LocalDate today = LocalDate.now();
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd 00:00:00");
            switch (orders.getTimeType()) {
                case "0":
                    wrapper.gt(Orders::getReceivingTime, today.format(formatter));
                    break;
                case "1":
                    LocalDate startOfWeek = today.with(ChronoField.DAY_OF_WEEK, 1);
                    wrapper.gt(Orders::getReceivingTime, startOfWeek.format(formatter));
                    break;
                case "2":
                    LocalDate startOfMonth = today.withDayOfMonth(1);
                    wrapper.gt(Orders::getReceivingTime, startOfMonth.format(formatter));
                    break;
            }
        }
    }

    // 提取转换逻辑的方法（示例）
    private OrdersVo<OrdersItemVo> convertToOrdersVo(Orders orders) {
        // 转换逻辑
        return (OrdersVo<OrdersItemVo>) orders; // 注意：这里需要确保类型安全，可能需要调整
    }

    // 提取转换逻辑的方法（示例）
    private OrdersItemVo convertToOrdersItemVo(OrdersItem ordersItem) {
        // 转换逻辑
        return (OrdersItemVo) ordersItem; // 注意：这里需要确保类型安全，可能需要调整
    }

}
